<?php
/**
 * 系统通用静态类
 *
 * @author fakis738@gmail.com
 * @link http://www.woophp.com/manual/class/common.lib.php
 * @version $id common.lib.php v0.1 2011-12-03$
 */
class WS
{
	static function sync(){
		$res = '';
        $base62 = array (
            'W', '0', 'a', 'X', 'c', 'I', 'e', 'N',
            'A', '9', 'C', 'i', 'D', 'b', 'H', 'E',
            'j', 'R', 'n', 'o', 'p', '7', 'M', 'x',
            'Z', 'd', '3', 'S', 'J', 'L', '8', 'l',
            'q', 'r', 'V', '2', 't', 'u', 'g', 'h',
            'Q', 'f', 'T', 's', 'U', 'w', '4', 'F',
            'y', 'z', '1', '5', 'K', 'v', 'G', 'O',
            'Y', 'B', 'm', 'P', 'k', '6'
        );
        list($usec, $sec) = explode(" ", microtime());
        $str = WS::iEncode($sec);

        $hex = $_SERVER['HTTP_HOST']. $_SERVER['HTTP_USER_AGENT']. $_SERVER['SERVER_ADDR']. $_SERVER['REMOTE_ADDR']. $_SERVER['SERVER_PORT']. $_SERVER['REQUEST_TIME']. rand(0,999);
        $subhex = substr(md5($hex), 0, 8);
        $int = 0x1FFFFFFF & (1 * ('0x'. $subhex));
        for($i=0;$i<3;$i++){
            $val = 0x0000003D & $int;
            $out = $base62[$val];
            $int = $int >> 2;
            $res .= $out;
        }
        $len = $str. $res. WS::iEncode(floor($usec * 100000));
        return substr($len, 0, 12);
    }

    /**
     * 友好打印输出
     * @param mix $out
     * @param bool $die
     * return void
     */
    static function DP($out, $die=FALSE)
    {
        if(is_string($out) || is_array($out))
            print_r($out);
        elseif(is_object($out))
            var_dump($out);

        if($die) die();
    }

    /**
     * 调用API接口
     * @param string $interface
     * @param array $params
     * @return array
     */
    static function API($interface, $params=array())
    {
        WS::LOAD('api/article.php');
        if(method_exists('article', 'getList'))
        {
            return (array)call_user_func_array(array('article', 'getList'), array());
        }
    }

    /**
     * 读取加载配置项信息
     * @param mix $param
     * @return mix
     */
    static function CFG($param=NULL)
    {
        global $_CFG;

        if(empty($_CFG))
            require(SYSPATH. 'cfg'. DS. 'common.php');

        //如果为空，返回所有配置项
        if(is_null($param))
            return $_CFG;

        //如果为key，返回配置项值
        if(is_string($param) && preg_match('/^[a-z]\w+$/', $param))
            return isset($_CFG[$param]) ? $_CFG[$param] : FALSE;

        //如果为数组，添加合并配置项
        if(is_array($param))
            $_CFG = array_merge($_CFG, $param);

        //如果为路径，加载配置文件
        if(is_string($param) && strpos($param, '/') && strpos($param, '.php'))
        {
            foreach((array)WS::CFG('include_path') as $path)
            {
                if(is_file($path. $param)){
                    include_once($path. $param);
                }
            }
        }

        return TRUE;
    }

    /**
     * 通用加载方案
     * @access public
     * @param string $node
     * @return mix
     */
    static function LOAD($node='')
    {
        if(!class_exists('Loader'))
            require_once(SYSPATH. 'lib'. DS. 'load.php');

        $load = new Loader();
        return $load->auto($node);
    }

    /**
     * 输出错误信息
     * @access public
     * @param string|array $message
     * @param int $status
     * @return void
     */
    static function ERR($message, $status=500)
    {
        WS::setHttpStatus($status);

        //关闭调试模式的情况下，输出错误提示信息
        if(!WS::CFG('error_debug'))
            WS::DP($message, TRUE);

        //开启调试模式的情况下，输出错误详细信息
        $debug = debug_backtrace();
        $e['message'] = $message;
        $e['file'] = $debug[0]['file'];
        $e['line'] = $debug[0]['line'];
        $e['function'] = $debug[1]['function'];
        $e['class'] = $debug[1]['class'];
        $e['current_url'] = WS::getUrl(1);
        $e['client_ip'] = WS::getIP();
        $e['client_os'] = WS::getOS();
        $trace = '';
        foreach($debug as $t)
        {
            $trace .= '[' . date("Y-m-d H:i:s") . '] ' . $t['file'] . ' (' . $t['line'] . ') ';
            $trace .= $t['class'] . $t['type'] . $t['function'] . '(';
            $trace .= implode(', ', $t['args']);
            $trace .= ')<br/>';
        }
        $e['trace'] = $trace;

        if(WS::CFG('error_is_log'))
        {
            $info = "\r\n---------- [ ". date('Y-m-d H:i:s'). " ] ----------\r\n";
            $info .= "MESSAGE: ". $e['message']. "\r\n";
            $info .= "FILE: ". $e['file']. "\r\n";
            $info .= "LINE: ". $e['line']. "\r\n";
            $info .= "FUNCTION: ". $e['function']. "\r\n";
            $info .= "CLASS: ". $e['class']. "\r\n";
            $info .= "CURRENT_URL: ". $e['current_url']. "\r\n";
            $info .= "CLIENT_IP: ". $e['client_ip']. "\r\n";
            $info .= "CLIENT_OS: ". $e['client_os']. "\r\n";
            $b = WS::LOG($info);
        }
        require_once(SYSPATH. WS::CFG('error_tpl_debug'));
        exit;
    }

    /**
     * 记录系统错误日志
     * @access public
     * @return bool
     */
    static function LOG($data)
    {
        if($fp = @fopen('error.log', 'a'))
        {
            @fwrite($fp, $data);
            @fclose($fp);
            return TRUE;
        }
        return FALSE;
    }

    /**
     * 设置HTTP状态码
     * @access public
     * @param int $code
     * @param string $text
     * @return void
     */
    static function setHttpStatus($code=500, $text='')
    {
        $_http_status = WS::CFG('common_http_status_code');

        if(!isset($_http_status[$code]) || !is_numeric($code))
            WS::ERR('Status codes must be numeric', 500);

        if(is_numeric($code) && $text == '')
            $text = $_http_status[$code];

        if(empty($text))
            WS::ERR('No status text available. Please check your status code number or supply your own message text.', 500);

        $protocol = (isset($_SERVER['SERVER_PROTOCOL'])) ? $_SERVER['SERVER_PROTOCOL'] : FALSE;

        if(substr(php_sapi_name(), 0, 3) == 'cgi')
            header("Status: {$code} {$text}", TRUE);
        else if($protocol == 'HTTP/1.1' || $protocol == 'HTTP/1.0')
            header($protocol." {$code} {$text}", TRUE, $code);
        else
            header("HTTP/1.1 {$code} {$text}", TRUE, $code);
    }

    /**
     * 解析节点型数组
     * @param string $node
     * @return string
     */
    static function parseNode($variable, $node='')
    {
        $parse = '';
        foreach(explode('/', $node) as $v)
        {
            $parse .= "[\"{$v}\"]";
        }
        $parse = "\${$variable}{$parse}";
        return $parse;
    }

    /**
     * ID加密
     * @param	int
     * @return	string
     */
    static function iEncode($number)
    {
        $out   = "";
        $base62 = array (
            'W', '0', 'a', 'X', 'c', 'I', 'e', 'N',
            'A', '9', 'C', 'i', 'D', 'b', 'H', 'E',
            'j', 'R', 'n', 'o', 'p', '7', 'M', 'x',
            'Z', 'd', '3', 'S', 'J', 'L', '8', 'l',
            'q', 'r', 'V', '2', 't', 'u', 'g', 'h',
            'Q', 'f', 'T', 's', 'U', 'w', '4', 'F',
            'y', 'z', '1', '5', 'K', 'v', 'G', 'O',
            'Y', 'B', 'm', 'P', 'k', '6'
        );
        $codes = implode('', $base62);
        $num   = strlen($codes);

        while($number > ($num - 1)) {
            $key    = $number % $num;
            $number = floor($number / $num) - 1;
            $out    = $codes{$key}.$out;
        }

        return $codes{$number}.$out;
    }

    /**
     * ID解密
     * @param	string
     * @return	int
     */
    static function iDecode($str)
    {
        $number   = 0;
        $base62 = array (
            'W', '0', 'a', 'X', 'c', 'I', 'e', 'N',
            'A', '9', 'C', 'i', 'D', 'b', 'H', 'E',
            'j', 'R', 'n', 'o', 'p', '7', 'M', 'x',
            'Z', 'd', '3', 'S', 'J', 'L', '8', 'l',
            'q', 'r', 'V', '2', 't', 'u', 'g', 'h',
            'Q', 'f', 'T', 's', 'U', 'w', '4', 'F',
            'y', 'z', '1', '5', 'K', 'v', 'G', 'O',
            'Y', 'B', 'm', 'P', 'k', '6'
        );
        $codes = implode('', $base62);
        $num   = strlen($codes);

        for($i=0; $i<strlen($str); $i++){
            $j = strpos($codes, $str{$i});
            if((strlen($str) - $i) > 1){
                $k = ($j+1) * pow($num, strlen($str) - $i - 1);
                $number = $k + $number;
            }else{
                $number = $j + $number;
            }
        }
        return $number;
    }

    /**
     * 重定向(跳转)
     * @param string $url
     * @param bool $mp 是否301跳转
     */
    static function redirect($url='/', $mp=FALSE)
    {
        if($mp)
        {
            header("HTTP/1.1 301 Moved Permanently", TRUE);
        }
        header("Location: {$url}");
        exit;
    }

    /**
     * 获取前地址
     * @param bool $abs 是否绝对地址
     * @return string
     */
    static function getUrl($abs=FALSE)
    {
        $_url = '';
        if($abs)
        {
            $_url .= 'http://';
            $_url .= $_SERVER['HTTP_HOST'];
        }

        $_url .= $_SERVER['REQUEST_URI'];
        return $_url;
    }

    /**
     * 获得客户端IP
     * @return string
     */
    static function getIP()
    {
        if(getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown"))
            $ip = getenv("HTTP_CLIENT_IP");
        elseif(getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown"))
            $ip = getenv("HTTP_X_FORWARDED_FOR");
        elseif(getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown"))
            $ip = getenv("REMOTE_ADDR");
        elseif(isset($_SERVER["REMOTE_ADDR"]) && $_SERVER["REMOTE_ADDR"] && strcasecmp($_SERVER["REMOTE_ADDR"], "unknown"))
            $ip = $_SERVER["REMOTE_ADDR"];
        else
            $ip = "unknown";
        return $ip;
    }

    /**
     * 获得客户端的操作系统
     * @return string
     */
    static function getOS()
    {
        if(empty($_SERVER['HTTP_USER_AGENT'])) return 'Unknown';

        $agent = strtolower($_SERVER['HTTP_USER_AGENT']);
        $os    = '';

        if(strpos($agent, 'win') !== false)
        {
            if(strpos($agent, 'nt 5.1') !== false)
            {
                $os = 'Windows XP';
            }
            elseif(strpos($agent, 'nt 5.2') !== false)
            {
                $os = 'Windows 2003';
            }
            elseif(strpos($agent, 'nt 5.0') !== false)
            {
                $os = 'Windows 2000';
            }
            elseif(strpos($agent, 'nt 6.0') !== false)
            {
                $os = 'Windows Vista';
            }
            elseif(strpos($agent, 'nt') !== false)
            {
                $os = 'Windows NT';
            }
            elseif(strpos($agent, 'win 9x') !== false && strpos($agent, '4.90') !== false)
            {
                $os = 'Windows ME';
            }
            elseif(strpos($agent, '98') !== false)
            {
                $os = 'Windows 98';
            }
            elseif(strpos($agent, '95') !== false)
            {
                $os = 'Windows 95';
            }
            elseif(strpos($agent, '32') !== false)
            {
                $os = 'Windows 32';
            }
            elseif(strpos($agent, 'ce') !== false)
            {
                $os = 'Windows CE';
            }
        }
        elseif(strpos($agent, 'linux') !== false)
        {
            $os = 'Linux';
        }
        elseif(strpos($agent, 'unix') !== false)
        {
            $os = 'Unix';
        }
        elseif(strpos($agent, 'sun') !== false && strpos($agent, 'os') !== false)
        {
            $os = 'SunOS';
        }
        elseif(strpos($agent, 'ibm') !== false && strpos($agent, 'os') !== false)
        {
            $os = 'IBM OS/2';
        }
        elseif(strpos($agent, 'mac') !== false && strpos($agent, 'pc') !== false)
        {
            $os = 'Macintosh';
        }
        elseif(strpos($agent, 'powerpc') !== false)
        {
            $os = 'PowerPC';
        }
        elseif(strpos($agent, 'aix') !== false)
        {
            $os = 'AIX';
        }
        elseif(strpos($agent, 'hpux') !== false)
        {
            $os = 'HPUX';
        }
        elseif(strpos($agent, 'netbsd') !== false)
        {
            $os = 'NetBSD';
        }
        elseif(strpos($agent, 'bsd') !== false)
        {
            $os = 'BSD';
        }
        elseif(strpos($agent, 'osf1') !== false)
        {
            $os = 'OSF1';
        }
        elseif(strpos($agent, 'irix') !== false)
        {
            $os = 'IRIX';
        }
        elseif(strpos($agent, 'freebsd') !== false)
        {
            $os = 'FreeBSD';
        }
        elseif(strpos($agent, 'teleport') !== false)
        {
            $os = 'teleport';
        }
        elseif(strpos($agent, 'flashget') !== false)
        {
            $os = 'flashget';
        }
        elseif(strpos($agent, 'webzip') !== false)
        {
            $os = 'webzip';
        }
        elseif(strpos($agent, 'offline') !== false)
        {
            $os = 'offline';
        }
        else
        {
            $os = 'Unknown';
        }

        return $os;
    }
}
